/*
 * Copyright (c) 2011. This file is public under GPLv3 license.
 * For more information about license please refer to http://www.gnu.org/licenses/gpl.html
 */

package com.freetools.watchdog.commands;

import com.freetools.watchdog.engine.DAO;
import com.freetools.watchdog.engine.UserInformation;
import com.freetools.watchdog.exceptions.ParametersErrorException;
import com.freetools.watchdog.model.Column;
import com.freetools.watchdog.model.CommandName;
import com.freetools.watchdog.model.IColumn;
import com.freetools.watchdog.model.IModelHolder;
import org.apache.log4j.Logger;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Creates columns in external database table and configure names
 * for groups when parsing process will be started.
 * <br/>
 * Format of the command:
 * <br/>
 * <br/>
 * <code>
 * -columns &lt;name&gt;[[*]&lt;type&gt;]]][{&lt;format&gt;}}]
 * </code>
 * <br/>
 * <br/>
 * <ul>
 * <li>name - column name. Can contain spaces in this case wrap all this parameter see examples</li>
 * <li>* - index marker. If it exists then index should be created except of clob columns</li>
 * <li>type - data type of the column. See table below to specify which name of data type to use</li>
 * <li>format - parsing format for timestamp type of columns. For more information of this format see {@link java.text.SimpleDateFormat}</li>
 * </ul>
 * To specify type of column and index creation policy follow the instructions below:
 * <table border="0" cellpadding="5" cellspacing="0"
 * summary="Supporting DB types of columns">
 * <p/>
 * <tr align="left">
 * <th bgcolor="#CCCCFF" align="left" id="name">DB's type name</th>
 * <th bgcolor="#CCCCFF" align="left" id="alias">Watch Dog's type name</th>
 * <th bgcolor="#CCCCFF" align="left" id="alias">Has format specification?</th>
 * <th bgcolor="#CCCCFF" align="left" id="alias">Can has an index?</th>
 * <th bgcolor="#CCCCFF" align="left" id="alias">Examples</th>
 * </tr>
 * <tr><th>&nbsp;</th></tr>
 * <tr>
 * <td>TIMESTAMP</td>
 * <td>
 * <ul>
 * <li>timestamp</li>
 * <li>date</li>
 * <li>time</li>
 * </ul>
 * </td>
 * <td>Yes</td>
 * <td>Yes</td>
 * <td>
 * <code>
 * time[*timestamp]{yyyy-MM-dd HH:mm:ss,SSS}<br/>
 * "created date[*date]{yyyy-MM-dd}"<br/>
 * logger_message_time[time]{yyyy-MM-dd HH:mm:ss,SSS}"
 * </code>
 * </td>
 * </tr>
 * <tr>
 * <td>BIGINT</td>
 * <td>
 * <ul>
 * <li>int</li>
 * <li>bigint</li>
 * <li>long</li>
 * </ul>
 * </td>
 * <td>No</td>
 * <td>Yes</td>
 * <td>
 * <code>
 * request_id[*long]<br/>
 * "request id[bigint]"
 * </code>
 * </td>
 * </tr>
 * <tr>
 * <td>varchar(1000)</td>
 * <td>&lt;default type&gt;
 * </td>
 * <td>No</td>
 * <td>Yes</td>
 * <td>
 * <code>
 * thread[*]<br/>
 * "thread id"
 * </code>
 * </td>
 * </tr>
 * <tr>
 * <td>clob</td>
 * <td>
 * <ul>
 * <li>clob</li>
 * <li>text</li>
 * </ul>
 * </td>
 * <td>No</td>
 * <td>No</td>
 * <td>
 * <code>
 * message[clob]<br/>
 * "log message[text]"
 * </code>
 * </td>
 * </tr>
 * </table>
 *
 * @author Michael Morozov
 */
@CommandName("columns")
public class ColumnsCmd extends Command
{
    private static final Logger log = Logger.getLogger(ColumnsCmd.class);

    public void execute(IModelHolder model) throws ParametersErrorException
    {
        if (getParameters().size() == 0)
        {
            showColumns(model);

            return;
        }
        Pattern dateFormat = Pattern.compile("^(\\w+)\\[([*]?)(?:date|time|timestamp)\\]\\{(.+)\\}", Pattern.CASE_INSENSITIVE);
        Pattern intFormat = Pattern.compile("^(\\w+)\\[([*]?)(?:int|bigint|long)\\]", Pattern.CASE_INSENSITIVE);
        Pattern clobFormat = Pattern.compile("^(\\w+)\\[[*]?(?:text|clob)\\]", Pattern.CASE_INSENSITIVE);
        Pattern justIndexFormat = Pattern.compile("^(\\w+)\\[[*]\\]", Pattern.CASE_INSENSITIVE);
        for (String p : getParameters())
        {
            Matcher m;

            if ((m = dateFormat.matcher(p)).matches())
            {
                model.getColumns().add(new Column(
                        m.group(1), //name
                        "timestamp", //type
                        m.group(3), //format
                        m.group(2).length() > 0//has index
                ));
            } else if ((m = intFormat.matcher(p)).matches())
            {
                model.getColumns().add(new Column(
                        m.group(1), //name
                        "bigint", //type
                        "", //format
                        m.group(2).length() > 0//has index
                ));
            } else if ((m = clobFormat.matcher(p)).matches())
            {
                model.getColumns().add(new Column(
                        m.group(1), //name
                        "clob", //type
                        "", //format
                        false
                ));
            } else if ((m = justIndexFormat.matcher(p)).matches())
            {
                model.getColumns().add(new Column(
                        m.group(1), //name
                        "varchar(1000)", //type
                        "", //format
                        true
                ));
            } else
            {
                model.getColumns().add(new Column(
                        p, //name
                        "varchar(1000)", //type
                        "", //format
                        false
                ));
            }
        }
        showColumns(model);
        DAO.createDB(model);

    }

    private void showColumns(IModelHolder model)
    {
        UserInformation.info("Current columns:");
        for (IColumn column : model.getColumns())
        {
            UserInformation.info(column.getName());
        }
    }

    @Override
    public boolean isMultipleParametrized()
    {
        return true;
    }
}
